import transform from "./transform.js";

/**
 * 获取当前浏览器窗口的缩放比例
 * @returns ratio
 */
export function getRatio(){
  let ratio = 1;
  if(window.devicePixelRatio !== undefined) {
    ratio = window.devicePixelRatio;
  }else if(window.outerWidth !== undefined && window.innerWidth !== undefined) {
    ratio = window.outerWidth / window.innerWidth;
  }
  return ratio;
}

/**
 * 创建正方形
 * @param {*} lng 经度
 * @param {*} lat 纬度
 * @param {*} meter 米
 * @returns [[lng, lat], [lng, lat]]
 */
export function getSquare(lng, lat, meter) {
  let [x, y] = transform.coordTransform("EPSG:4326", "EPSG:3857", [lng, lat]);
  let leftTop = [x - meter, y + meter];
  let rightTop = [x + meter, y + meter];
  let rightBottom = [x + meter, y - meter];
  let leftBottom = [x - meter, y - meter];
  return [leftTop, rightTop, rightBottom, leftBottom].map(v => transform.coordTransform("EPSG:3857", "EPSG:4326", v))
}

/**
 * 计算两点的偏航角，返回度数
 * @param {*} point1 点位1 { lng, lat }
 * @param {*} point2 点位2 { lng, lat }
 * @returns Number 度数
 */
export function getAngle(point1, point2){
  let ret;
  let w1 = point1.lat / 180 * Math.PI;
  let j1 = point1.lng / 180 * Math.PI;

  let w2 = point2.lat / 180 * Math.PI;
  let j2 = point2.lng / 180 * Math.PI;

  ret = 4 * Math.pow(Math.sin((w1 - w2) / 2), 2) - Math.pow(Math.sin((j1 - j2) / 2) * (Math.cos(w1) - Math.cos(w2)), 2);
  ret = Math.sqrt(ret);

  let temp = Math.sin((j1 - j2) / 2) * (Math.cos(w1) + Math.cos(w2));
  ret = ret / temp;

  ret = Math.atan(ret) / Math.PI * 180 ;
  ret += 90;
  
  // 判定追踪单个点的具体情况,从而调整ret的值
  if(j1 - j2 < 0) {
    if(w1 - w2 < 0) {
      ret;
    }else {
      ret = -ret + 180;
    }
  }else {
    if(w1 - w2 < 0){
      ret = 180 + ret;
    }else {
      ret = -ret;
    }
  }
  return ret;
}

/**
 * 根据行列号xyz转经纬度坐标
 * @param {*} z 
 * @param {*} x 
 * @param {*} y 
 * @returns [lon, lat]
 */
export function XYZtoLonlat(z, x, y) {
  let n = Math.pow(2, z);
  let lon = x / n * 360 - 180;
  let lat = Math.atan(Math.sinh(Math.PI * (1 - 2 * y / n)));
  lat = lat * 180 / Math.PI;
  return [lon, lat];
}

/**
 * 计算风场时间
 * @param {*} time "2023-02-27 13:00:00"
 * @param {*} fileType 文件类型nc/json
 */
export function getWindFilePath(time, fileType = "json") {  //加载风场
  let windKpa = "lev_10_m_above_ground";  //风场大气压
  let year = time.substr(0, 4);
  let month = time.substr(5, 2);
  let day = time.substr(8, 2);
  let hour = time.substr(11, 2);
  let timeObj = new Date();
  timeObj.setFullYear(year, parseInt(month) - 1, day);
  timeObj.setHours(hour);

  let cTime = new Date();//当前时间
  let dif_hour = timeObj.getTime() - cTime.getTime();
  let backTime;
  if (dif_hour > 0) { //传入时间大于当前时间
    backTime = new Date(timeObj.getTime() - 12 * 60 * 60 * 1000 - dif_hour); //数据推迟小时数
  } else {
    backTime = new Date(timeObj.getTime() - 12 * 60 * 60 * 1000); //数据推迟小时数
  }
  let backHour = Math.floor(backTime.getHours() / 6) * 6;    //计算最新预报时间点
  let backMonth = (backTime.getMonth() + 1 < 10) ? "0" + (backTime.getMonth() + 1) : (backTime.getMonth() + 1);
  let backDay = (backTime.getDate() < 10) ? "0" + backTime.getDate() : backTime.getDate();
  let recordFile = backTime.getFullYear() + backMonth + backDay + ((backHour < 10) ? "0" + backHour : backHour);
  let goHour = 0;  //计算从预报时间点往后推的小时数
  if ((backHour + 12) > 24) { //考虑时差
    goHour = parseInt(hour) - (backHour + 12 - 24);
  } else {
    goHour = parseInt(hour) - (backHour + 12);
  }
  let fCount = (goHour < 10) ? "0" + goHour : goHour;
  let windDataUrl = "/wind/" + recordFile + "/" + windKpa + "/wind_" + windKpa + "_" + recordFile + "_0" + fCount + "." + fileType;
  return windDataUrl;
}

/**
 * 对象方法劫持函数，监听方法执行前后
 * @param {
 *   object: Object, //劫持对象
 *   methodName: String|Array, //要劫持方法名
 *   before: Function, //方法执行前
 *   after: Function, //方法执行后
 * } options
 */
export function objectMethodHook({object, methodName, before, after}) {
  const aopFunc = (methodName) => {
    let orign = object[methodName];
    object[methodName] = function(...args) {
      before(methodName, args);
      let result = orign.call(object, ...args);
      after(methodName, args);
      return result;
    }
  }
  let methodList = Array.isArray(methodName) ? methodName : [methodName];
  methodList.forEach(v => aopFunc(v));
}